# coding=utf-8
import binascii
import datetime
import json
import os
import queue
import random
import select
import socket
import struct
import socket
import sys
import threading
import time
from ctypes import *
import pyperclip
from tool_base import *
from PyQt6.QtCore import *
from PyQt6.QtGui import *
from PyQt6.QtWidgets import *
from ui.ui_main_windows import *
from format_change import *
from phy.uart.uart_main import *
import pylink
from pylink.errors import *
import tempfile
from get_dev_base_info import get_dev_base_info
import shutil
import MergeHex
import threading

MAX_RCV_NUM = 10
_translate = QtCore.QCoreApplication.translate
main_wdbg = logging.getLogger('Main')
main_app_wdbg = logging.getLogger('main_app')
WINDOWS_wdbg = logging.getLogger('WINDOW')
CAN_ID_DEVICE_SN_SET_RO_GET = 0X00C
RECORD_PAGE_ENTRY = 50
TRM_RUN_MODE = 1

def get_list(data):
    out = []
    if data != '':
        data1 = data.split((','))
        for i in range(0, int(len(data1)/4)):
            out.append([data1[i*4 + 2], '%0.8f'%(float(data1[i*4])),'%0.8f'%(float(data1[i*4 + 1]))])
        return out
    else:
        return None

(SEND_VIRTUAL_CAN_DATA,SEND_VIRTUAL_CAN_FILE,SEND_VIRTUAL_DOWNFILE,SEND_VIRTUAL_DOWNLAOD_ST) = range(1,5) 


def get_crc_data(data):
    gs_bzip2CrcTable = [ 
            0x00000000,0x04c11db7,0x09823b6e,0x0d4326d9,0x130476dc,0x17c56b6b,0x1a864db2,0x1e475005,0x2608edb8,0x22c9f00f,0x2f8ad6d6,0x2b4bcb61,0x350c9b64,0x31cd86d3,0x3c8ea00a,0x384fbdbd,
            0x4c11db70,0x48d0c6c7,0x4593e01e,0x4152fda9,0x5f15adac,0x5bd4b01b,0x569796c2,0x52568b75,0x6a1936c8,0x6ed82b7f,0x639b0da6,0x675a1011,0x791d4014,0x7ddc5da3,0x709f7b7a,0x745e66cd,
            0x9823b6e0,0x9ce2ab57,0x91a18d8e,0x95609039,0x8b27c03c,0x8fe6dd8b,0x82a5fb52,0x8664e6e5,0xbe2b5b58,0xbaea46ef,0xb7a96036,0xb3687d81,0xad2f2d84,0xa9ee3033,0xa4ad16ea,0xa06c0b5d,
            0xd4326d90,0xd0f37027,0xddb056fe,0xd9714b49,0xc7361b4c,0xc3f706fb,0xceb42022,0xca753d95,0xf23a8028,0xf6fb9d9f,0xfbb8bb46,0xff79a6f1,0xe13ef6f4,0xe5ffeb43,0xe8bccd9a,0xec7dd02d,
            0x34867077,0x30476dc0,0x3d044b19,0x39c556ae,0x278206ab,0x23431b1c,0x2e003dc5,0x2ac12072,0x128e9dcf,0x164f8078,0x1b0ca6a1,0x1fcdbb16,0x018aeb13,0x054bf6a4,0x0808d07d,0x0cc9cdca,
            0x7897ab07,0x7c56b6b0,0x71159069,0x75d48dde,0x6b93dddb,0x6f52c06c,0x6211e6b5,0x66d0fb02,0x5e9f46bf,0x5a5e5b08,0x571d7dd1,0x53dc6066,0x4d9b3063,0x495a2dd4,0x44190b0d,0x40d816ba,
            0xaca5c697,0xa864db20,0xa527fdf9,0xa1e6e04e,0xbfa1b04b,0xbb60adfc,0xb6238b25,0xb2e29692,0x8aad2b2f,0x8e6c3698,0x832f1041,0x87ee0df6,0x99a95df3,0x9d684044,0x902b669d,0x94ea7b2a,
            0xe0b41de7,0xe4750050,0xe9362689,0xedf73b3e,0xf3b06b3b,0xf771768c,0xfa325055,0xfef34de2,0xc6bcf05f,0xc27dede8,0xcf3ecb31,0xcbffd686,0xd5b88683,0xd1799b34,0xdc3abded,0xd8fba05a,
            0x690ce0ee,0x6dcdfd59,0x608edb80,0x644fc637,0x7a089632,0x7ec98b85,0x738aad5c,0x774bb0eb,0x4f040d56,0x4bc510e1,0x46863638,0x42472b8f,0x5c007b8a,0x58c1663d,0x558240e4,0x51435d53,
            0x251d3b9e,0x21dc2629,0x2c9f00f0,0x285e1d47,0x36194d42,0x32d850f5,0x3f9b762c,0x3b5a6b9b,0x0315d626,0x07d4cb91,0x0a97ed48,0x0e56f0ff,0x1011a0fa,0x14d0bd4d,0x19939b94,0x1d528623,
            0xf12f560e,0xf5ee4bb9,0xf8ad6d60,0xfc6c70d7,0xe22b20d2,0xe6ea3d65,0xeba91bbc,0xef68060b,0xd727bbb6,0xd3e6a601,0xdea580d8,0xda649d6f,0xc423cd6a,0xc0e2d0dd,0xcda1f604,0xc960ebb3,
            0xbd3e8d7e,0xb9ff90c9,0xb4bcb610,0xb07daba7,0xae3afba2,0xaafbe615,0xa7b8c0cc,0xa379dd7b,0x9b3660c6,0x9ff77d71,0x92b45ba8,0x9675461f,0x8832161a,0x8cf30bad,0x81b02d74,0x857130c3,
            0x5d8a9099,0x594b8d2e,0x5408abf7,0x50c9b640,0x4e8ee645,0x4a4ffbf2,0x470cdd2b,0x43cdc09c,0x7b827d21,0x7f436096,0x7200464f,0x76c15bf8,0x68860bfd,0x6c47164a,0x61043093,0x65c52d24,
            0x119b4be9,0x155a565e,0x18197087,0x1cd86d30,0x029f3d35,0x065e2082,0x0b1d065b,0x0fdc1bec,0x3793a651,0x3352bbe6,0x3e119d3f,0x3ad08088,0x2497d08d,0x2056cd3a,0x2d15ebe3,0x29d4f654,
            0xc5a92679,0xc1683bce,0xcc2b1d17,0xc8ea00a0,0xd6ad50a5,0xd26c4d12,0xdf2f6bcb,0xdbee767c,0xe3a1cbc1,0xe760d676,0xea23f0af,0xeee2ed18,0xf0a5bd1d,0xf464a0aa,0xf9278673,0xfde69bc4,
            0x89b8fd09,0x8d79e0be,0x803ac667,0x84fbdbd0,0x9abc8bd5,0x9e7d9662,0x933eb0bb,0x97ffad0c,0xafb010b1,0xab710d06,0xa6322bdf,0xa2f33668,0xbcb4666d,0xb8757bda,0xb5365d03,0xb1f740b4 ]
    gs_bzip2CrcRemainder = 0xFFFFFFFF
    crc = gs_bzip2CrcRemainder

    for i in range(0, len(data)):
        temp = data[i]
        tmp = ((crc >> 24) ^ data[i])& 0xff
        crc = (crc << 8) ^ gs_bzip2CrcTable[tmp]
    return (crc ^0xFFFFFFFF) & 0xffffffff

def get_data_hex(data):
    out = ''
    for i in range(0, len(data)):
        out += '%02X' % data[i]
    return out

class QSSLoader():
    def __init__(self):
        pass
    @staticmethod
    def read_qss_file(qss_file_name):
        with open(qss_file_name, 'r', encoding='UTF-8') as file:
            return file.read()

class ConfigDeviceLoader:
    def __init__(self, config_file='devInfoCfg.ini'):
        self.config_file = config_file

    def loadDeviceConfig(self):
        options = []
        script_dir = os.path.dirname(os.path.abspath(__file__))
        config_path = os.path.join(script_dir, self.config_file)
        config = configparser.ConfigParser()
        config.read(config_path)

        if not config.sections():
            return None  # 返回空或特殊值

        for section in config.sections():
            if section.startswith('DEVICETYPE'):
                for key, value in config.items(section):
                    if key.startswith('devicetype'):
                        options.append(value)

        if not options:
            return None  # 返回空或特殊值

        return options
    def getDeviceSection(self, device_type):
        config = configparser.ConfigParser()
        config.read(self.config_file)

        # 根据设备类型构造section名称
        section_name = device_type

        # 如果section存在，则获取其内容；否则，返回一个空字典
        if config.has_section(section_name):
            device_section = dict(config[section_name])

            # 检查必需的配置项
            required_keys = ["imagetype", "hq_model", "gb_model"]
            missing_keys = [key for key in required_keys if key not in device_section]

            # 如果缺少任何必需的键，打印警告并返回空字典
            if missing_keys:
                print(f"警告: 在设备类型 '{section_name}' 的配置部分中缺少以下必需项: {', '.join(missing_keys)}")
                return {}
            print(f"Found configuration section for device type '{device_type}':\n{device_section}")
        else:
            print(f"No configuration section found for device type '{device_type}'. Returning an empty dictionary.")
            device_section = {}
        return device_section

def bin_to_hex(filename, outFileName, address: int):
    hd = open(filename, 'rb')
    src_data = hd.read(os.stat(filename).st_size)
    hd.close()

    if len(src_data) == 0:
        return 0

    out_file = open(outFileName, 'w', encoding='utf-8')
    all_len = len(src_data)
    offset = 0
    all_offset = 0
    blk_size = 0
    offset_addr = address
    while all_offset < all_len:

        if all_len > all_offset + 16:
            blk_size = 16
        else:
            blk_size = all_len - all_offset

        if offset % 65536 == 0:
            data_temp = ':02000004%04X' % ((offset_addr >> 16) & 0xffff)
            src = binascii.a2b_hex(data_temp[1:])
            data_temp += '%02X\n' % get_sum(src)
            out_file.write(data_temp)
            offset_addr += 65536
            offset = 0
        data_temp = ':%02X%04X00' % (blk_size, offset)
        data_temp += get_data_hex(src_data[all_offset:all_offset + blk_size])
        src = binascii.a2b_hex(data_temp[1:])
        data_temp += '%02X\n' % get_sum(src)
        offset += blk_size
        out_file.write(data_temp)
        all_offset += blk_size
        if all_offset == all_len:
            break
    data_temp = ':00000001FF\n'
    out_file.write(data_temp)
    out_file.close()
    return 1


def get_file_data(pathx):
    hd = open(pathx, 'rb')
    sbl = bytearray()
    sbl.extend(hd.read(1024 * 1024*30))
    hd.close()
    return sbl

def bin_to_hex(filename, outFileName, address: int):
    hd = open(filename, 'rb')
    src_data = hd.read(os.stat(filename).st_size)
    hd.close()

    if len(src_data) == 0:
        return 0

    out_file = open(outFileName, 'w', encoding='utf-8')
    all_len = len(src_data)
    offset = 0
    all_offset = 0
    blk_size = 0
    offset_addr = address
    while all_offset < all_len:

        if all_len > all_offset + 16:
            blk_size = 16
        else:
            blk_size = all_len - all_offset

        if offset % 65536 == 0:
            data_temp = ':02000004%04X' % ((offset_addr >> 16) & 0xffff)
            src = binascii.a2b_hex(data_temp[1:])
            data_temp += '%02X\n' % get_sum(src)
            out_file.write(data_temp)
            offset_addr += 65536
            offset = 0
        data_temp = ':%02X%04X00' % (blk_size, offset)
        data_temp += get_data_hex(src_data[all_offset:all_offset + blk_size])
        src = binascii.a2b_hex(data_temp[1:])
        data_temp += '%02X\n' % get_sum(src)
        offset += blk_size
        out_file.write(data_temp)
        all_offset += blk_size
        if all_offset == all_len:
            break
    data_temp = ':00000001FF\n'
    out_file.write(data_temp)
    out_file.close()
    return 1

class TProductInfo:
    _fields_ = [
        ('date', c_uint32),
        ('dev_no', c_uint32),
        ('serial_no', c_uint8 * 16),
        ('internal_model', c_uint8 * 16),
        ('hw_ver', c_uint8 * 4),
        ('manufacturer_id', c_uint8 * 6),
        ('standard_model', c_uint8 * 16),
        ('hwconfig', c_uint8 * 6),
        # ('reserved', c_uint8 * 120),  # 如果需要的话，可以取消注释这一行
    ]
    def __init__(self):
        self.date = 0                   # 产品 - 烧写日期，4字节无符号整数
        self.dev_no = 0                 # 产品 - 设备号，4字节无符号整数
        self.serial_no = ""             # 产品 - 设备序列号，16字节字符串
        self.internal_model = ""        # 产品 - 产品型号 "ABOS 3.0"，16字节字符串
        self.hw_ver = ""                # 产品 - 硬件版本，4字节字符串
        self.manufacturer_id = ""       # 产品 - 制造商ID，6字节字符串
        self.standard_model = ""        # 产品 - 产品型号 "ABOS 3.0"，16字节字符串
        self.hwconfig = ""              # 产品 - 鸿泉硬件标示，6字节字符串
        #self.reserved = bytearray(120) # 保留,实际是有这个字段

class InputTProductInfo(Structure):
    _fields_ = [
        ('date', c_uint32),
        ('dev_no', c_uint32),
        ('serial_no', c_uint8 * 16),
        ('internal_model', c_uint8 * 16),
        ('hw_ver', c_uint8 * 4),
        ('manufacturer_id', c_uint8 * 6),
        ('standard_model', c_uint8 * 16),
        ('hwconfig', c_uint8 * 6),
        # ('reserved', c_uint8 * 120),  # 如果需要的话，可以取消注释这一行
    ]

class MergeHexThread(threading.Thread):
    def __init__(self, config_file):
        super().__init__()
        self.config_file = config_file
        self.error_msgs = None

    def run(self):
        error_msgs = MergeHex.main(self.config_file)




class mian_window(QMainWindow):
    signal_dis = pyqtSignal(tuple)
    can_hd = None
    rx_signal = pyqtSignal(dict)
    signal_main_result_add = pyqtSignal(str)
    signal_set_info_check = pyqtSignal(str)
    signal_clear_get_info = pyqtSignal()
    signal_jlink_log_add = pyqtSignal(str)
    signal_virtual_add = pyqtSignal(str)
    signal_ye_leng_log = pyqtSignal(str)
    signal_jlink_log_clear = pyqtSignal()
    signal_ye_leng_log_clear = pyqtSignal()

    single_can_open = pyqtSignal(dict)
    signal_j1939_set_val = pyqtSignal(int)
    signal_uart_log_clear = pyqtSignal()
    signal_uart_log_add  = pyqtSignal(str)
    signal_message_clear = pyqtSignal()
    signal_message_set  = pyqtSignal(str)
    phy_addr = []
    phy_rx_addr = []
    phy_tx_addr = []
    uds_rx_addr = []
    uds_tx_addr = []
    decode_all_len = 0
    wait_sn = 0
    fram_canid = 0
    decode_id = 0
    tx_frame = None
    func_addr = []
    send_time = 0
    module = ('报文检测与发送','MAP信息查询','小工具','传感器','长期测试')
    module_rec_data_hd = None
    module_map = None
    run_module = 0
    timer_cnt = 0
    dev_sn_dict = {}
    #长期测试内存读写测试
    long_test_mem_time = 0
    long_test_mem_can_id = 0x700
    long_test_mem_address = 0
    long_test_mem_len = 0
    long_test_base_timer = None
    log_record_mark = 0
    log_record_name = ''
    file_path = ['','','']
    cfg = {}
    send_dis_ctrl = []
    single_uart_hd = pyqtSignal(dict)

    virtual_stop = 0

    def stop(self):
        self.uart_cfg_hd.stopx()
        pass

    def set_speed(self, val):
        self.signal_j1939_set_val.emit(val)

    def slot_menu_triggered(self, act:QAction):
        if act.text() == 'UART配置':
            self.uart_cfg_hd.show()
        pass

    def slot_uart_send_key(self):
        try:
            
            temp = bytearray(0)
            if self.ui.comboBox_7.currentText() == 'hex':
                temp = binascii.a2b_hex(self.ui.textEdit.toPlainText().replace('\n','').replace(' ',''))    
                
            else:
                temp = self.ui.textEdit.toPlainText().encode()

            if len(temp):
                if self.ui.checkBox_7.isChecked():
                    self.signal_uart_log_add.emit( get_time_str1() +'TX[%d]'%len(temp) + get_hex_data(temp) + '\n')
                self.uart_cfg_hd.send_data(temp)
            pass
        except Exception as e:
            msg = printf_except_info(e)
            self.signal_message_set.emit('故障:'+ get_time_str1() + msg)

    def slot_uart_repeat_send(self, st):
        if st == True:
            temp = bytearray(0)
            if self.ui.comboBox_7.currentText() == 'hex':
                temp = binascii.a2b_hex(self.ui.textEdit.toPlainText().replace('\n','').replace(' ',''))    
                
            else:
                temp = self.ui.textEdit.toPlainText().encode()

            if len(temp) > 0:
                self.uart_cfg_hd.repeat_send(True, self.ui.spinBox_2.value(), temp)
        else:
            self.uart_cfg_hd.repeat_send(False, 0, None)
            pass

    def uart_rec_hd(self, msg:dict):
        try:
            if 'cmd' in msg.keys():
                if msg['cmd'] == CMD_REC_DATA:
                    dis_msg = ''
                    mode = self.ui.comboBox.currentText()
                    if self.ui.checkBox_5.isChecked():
                            dis_msg += get_time_str1()
                            if mode != '超时显示':
                                dis_msg += '\n'
                    cfg = {}
                    cfg['type'] = self.ui.comboBox_4.currentText()
                    cfg['scale'] = self.ui.comboBox_2.currentText()
                    cfg['biglit'] = self.ui.comboBox_6.currentText()

                    if mode == '超时显示':#超时显示    
                        dis_msg += get_dis_data(cfg, msg['data'],len(msg['data']))
                    else:
                        dis_msg += get_dis_data(cfg, msg['data'], self.ui.spinBox.value())
                    if self.ui.checkBox_6.isChecked():
                        pass
                    else:
                        self.signal_uart_log_add.emit(dis_msg) 

                elif msg['cmd'] == UART_ST_OPEN_ERR:
                    self.signal_message_set.emit('故障:'+ get_time_str1() + msg['data'])
                elif msg['cmd'] == UART_ST_SAVE_DATA:#参数保存
                    for key, val in msg['data'].items():
                        set_cfg('uart_cfg',key,'{}'.format(val))
        except Exception as e:
            msg = printf_except_info(e)
            self.signal_message_set(msg)

    def slot_jlink_read_devInfo(self):
        try:
            temp =  self.ui.comboBox_22.currentText()
            if temp == '':
                self.alarm('警告','请检查jlink是否正常接入 点击刷新')
                return
        
            self.signal_jlink_log_clear.emit()
            temp = '0000a000'
            hex_val = int(temp, 16)
            self.jlink = pylink.JLink()
            self.jlink.open()
            self.jlink.set_tif(pylink.enums.JLinkInterfaces.SWD)  # 成功返回True
            self.jlink.connect(self.ui.DevicelineEdit.text())  # 成功无返回
            temp = bytearray(self.jlink.memory_read(hex_val, int(72)))
            hex_data = [hex(x) for x in temp]
            # 打印转换后的hex_data列表
            #print(hex_data)

            # 创建一个空列表用于存储转换后的整数数据
            converted_data = []

            # 遍历 hex_data 列表中的每个元素
            for item in hex_data:
                # 去掉字符串前缀 '0x'，并将其转换为十进制整数
                decimal_value = int(item, 16)
                # 将转换后的值添加到 converted_data 列表中
                converted_data.append(decimal_value)

            # 打印转换后的整数列表
            #print(converted_data)

            # 创建 TProductInfo 实例
            product_info = TProductInfo()

            # 将 converted_data 中的数据赋值给 TProductInfo 结构体中相应的字段 解包并赋值给 TProductInfo 结构体中相应字段
            product_info.date, product_info.dev_no = struct.unpack("<II", bytes(converted_data[:8]))
            product_info.serial_no = bytes(converted_data[8:24])
            product_info.internal_model = bytes(converted_data[24:40])
            product_info.hw_ver = struct.unpack('<I', bytes(converted_data[40:44]))[0]
            product_info.manufacturer_id = bytes(converted_data[44:50])
            product_info.standard_model = bytes(converted_data[50:66])
            product_info.hwconfig = bytes(converted_data[66:72])
            #product_info.reserved = bytes(converted_data[72:192])

            # 解析devno
            dev_base_info = get_dev_base_info(product_info.dev_no)

            # 打印 TProductInfo 结构体的字段值
            self.signal_jlink_log_add.emit('读取到设备信息为:' + '\r\n')
            self.signal_jlink_log_add.emit('dev_info.timestamp is: ' + str(product_info.date) + '\r\n')
            self.signal_jlink_log_add.emit('dev_info.dev_no is: ' + str(product_info.dev_no) + '\r\n')
            self.signal_jlink_log_add.emit('dev_info.serial_no is: ' + product_info.serial_no.decode(errors='ignore').split('\x00')[0])
            self.signal_jlink_log_add.emit('，解析到终端ID为：' + f"{(dev_base_info.Year - 2000):02d}" + f"{dev_base_info.Month:02d}" + f"{dev_base_info.Day:02d}" + f"{dev_base_info.No:04d}")
            self.signal_jlink_log_add.emit('，终端ID生成日期为：' + str(datetime.datetime.fromtimestamp(product_info.date).strftime('%Y-%m-%d %H:%M:%S')) + f"，序号为：{dev_base_info.No:04d}" + '\r\n')
            self.signal_jlink_log_add.emit('dev_info.internal_model is: ' + product_info.internal_model.decode() + '\r\n')
            self.signal_jlink_log_add.emit('dev_info.hw_ver is: ' + str(product_info.hw_ver)+ '\r\n')
            self.signal_jlink_log_add.emit('dev_info.manufacturer_id is: ' + product_info.manufacturer_id.decode() + '\r\n')
            self.signal_jlink_log_add.emit('dev_info.standard_model is: ' + product_info.standard_model.decode() + '\r\n')
            self.signal_jlink_log_add.emit('dev_info.hwconfig is: ' + str('0x' + (product_info.hwconfig.hex())) + '\r\n')

            # 为读出的设备生成烧写包
            # 获取选择的设备类型
            selected_device = self.ui.deviceTypeCb.currentText()
            
            config_loader = ConfigDeviceLoader()
            device_config = config_loader.getDeviceSection(selected_device)
            # 打印找到的设备类型配置节内容
            self.signal_jlink_log_add.emit(f"找到'{selected_device}'型号终端的配置项:\r\n")
            # 检查device_config是否为空
            if device_config:
                for key, value in device_config.items():
                    self.signal_jlink_log_add.emit(f"{key}: {value}\r\n")
            else:
                self.signal_jlink_log_add.emit("该型号终端的配置信息不全,请检查配置文件！\r\n")
                return

            inputproduct_info = InputTProductInfo()
            inputproduct_info.internal_model = (c_uint8 * 16)(*device_config.get("hq_model").encode('utf-8')[:16])  # 终端内部型号
            inputproduct_info.standard_model = (c_uint8 * 16)(*device_config.get("gb_model").encode('utf-8')[:16])  # 终端标准型号
            # 预留其他信息，可能还需要进行更改！！！，如果更改了，还需要对应的改下方的非空判断

            if inputproduct_info.internal_model is not None and inputproduct_info.standard_model is not None:
                self.signal_jlink_log_add.emit("配置信息有效！\r\n")
            else:
                # 数据无效或为0
                self.signal_jlink_log_add.emit("配置信息类型错误，请检查配置文件！\r\n")
                return    

            # 根据选择的设备类型拼接动态库路径
            library_path = os.path.join(".", "img", "generateID.dll")
            # print(library_path)
            
            # 检查文件是否存在
            if not os.path.exists(library_path):
                QMessageBox.critical(self, "错误", "动态库文件不存在！")
                return

            # 加载动态链接库
            try:
                lib = cdll.LoadLibrary(library_path)
            except Exception as e:
                QMessageBox.critical(self, "错误", f"动态库加载失败：{e}")
                return

            input_str = device_config.get("imagetype")

            # 将字符串编码为字节，并创建一个可写的字节数组
            encoded_str = input_str.encode('utf-8')
            byte_array = bytearray(encoded_str)

            # 从可写的字节数组创建 ctypes 数组并获取其指针
            input_str_array = (c_ubyte * len(byte_array)).from_buffer(byte_array)
            input_str_ptr = cast(input_str_array, POINTER(c_ubyte))

            # 调用库中的函数
            result = lib.generateID(dev_base_info.Year, dev_base_info.Month, dev_base_info.Day, dev_base_info.No, input_str_ptr, inputproduct_info)

            if result == 0:
                try:
                    shutil.move(r".\0xA000bin.bin", r".\img\0xA000bin.bin")
                    self.signal_jlink_log_add.emit('生成的终端ID为：' + f"{dev_base_info.Year - 2000}" + f"{dev_base_info.Month:02d}" + f"{dev_base_info.Day:02d}" + f"{(dev_base_info.No):04d}" +'，ID文件在img目录下，文件名：0xA000bin.bin' + '\r\n')
                
                    # temp_dir = tempfile.gettempdir()
                    # print("DLL缓存路径：", temp_dir)
                    
                    dir_path = os.path.dirname(os.path.abspath(sys.argv[0]))  # 获取当前主程序所在的目录路径
                    config_file = os.path.join(dir_path, 'config.json')  # 拼接路径，获取配置文件的绝对路径
                    
                    # 调用合成脚本合成烧写hex文件
                    # error_msgs = MergeHex.main(config_file)
                    # 创建并启动线程
                    merge_hex_thread = MergeHexThread(config_file)
                    merge_hex_thread.start()
                    # 等待线程执行完成
                    merge_hex_thread.join()
                    # 获取线程的返回值
                    error_msgs = merge_hex_thread.error_msgs

                    if error_msgs is None:
                        self.signal_jlink_log_add.emit('生成的hex烧写文件为：MergedHexFile.hex，保存在程序运行运行目录下，烧写地址为0x00000000' + '\r\n')
                    else:
                        print('以下错误发生了：')
                        for error_msg in error_msgs:
                            self.signal_jlink_log_add.emit(error_msg)

                except Exception as e:
                    self.signal_jlink_log_add.emit(f"移动文件时发生错误：{e}" + '\r\n')
                    print(f"移动文件时发生错误：{e}")
            else:
                print("文件生成失败,错误码："+ str(result))



        except JLinkException as e:
            self.signal_jlink_log_add.emit('警告:{}'.format(e))

        except Exception as e:
            msg = '读取失败..  {}:{} {} '.format(e.__traceback__.tb_frame.f_globals["__file__"],
                                                 e.__traceback__.tb_lineno, e)
            self.signal_jlink_log_add.emit(msg)
        finally:
            if self.jlink is not None:
                self.jlink.close()
                self.jlink = None
            
    def slot_jlink_set_devInfo(self):
        # 获取当前本地时间
        current_time = datetime.datetime.now()
        # 获取当前日期
        current_date = current_time.date()
        # 配置文件路径
        config_path = "devInfoCfg.ini"

        # 检查配置文件是否存在
        if not os.path.exists(config_path):
            # 如果配置文件不存在，则创建文件，并设置默认值
            config = configparser.ConfigParser()
            config["devInfo"] = {"last_date": str(current_date), "last_value": "0"}

            with open(config_path, "w") as config_file:
                config.write(config_file)

        # 读取上次保存的日期和数值
        config = configparser.ConfigParser()
        config.read(config_path)

        last_date_str = config.get("devInfo", "last_date", fallback="")
        last_value = config.getint("devInfo", "last_value", fallback=0)

        if last_date_str:
            last_date = datetime.date.fromisoformat(last_date_str)
        else:
            last_date = None

        # 判断日期是否相同
        if last_date != current_date:
            # 如果日期不同，将last_value置为0
            last_value = 0
            # 更新配置文件中的last_date和last_value值
            config.set("devInfo", "last_date", str(current_date))
            config.set("devInfo", "last_value", str(last_value))
            with open(config_path, "w") as config_file:
                config.write(config_file)

        # 获取选择的设备类型
        selected_device = self.ui.deviceTypeCb.currentText()
        
        config_loader = ConfigDeviceLoader()
        device_config = config_loader.getDeviceSection(selected_device)
        # 打印找到的设备类型配置节内容
        self.signal_jlink_log_add.emit(f"找到'{selected_device}'型号终端的配置项:\r\n")
        # 检查device_config是否为空
        if device_config:
            for key, value in device_config.items():
                self.signal_jlink_log_add.emit(f"{key}: {value}\r\n")
        else:
            self.signal_jlink_log_add.emit("该型号终端的配置信息不全,请检查配置文件！\r\n")
            return

        inputproduct_info = InputTProductInfo()
        inputproduct_info.internal_model = (c_uint8 * 16)(*device_config.get("hq_model").encode('utf-8')[:16])  # 终端内部型号
        inputproduct_info.standard_model = (c_uint8 * 16)(*device_config.get("gb_model").encode('utf-8')[:16])  # 终端标准型号
        # 预留其他信息，可能还需要进行更改！！！，如果更改了，还需要对应的改下方的非空判断

        if inputproduct_info.internal_model is not None and inputproduct_info.standard_model is not None:
            self.signal_jlink_log_add.emit("配置信息有效！\r\n")
        else:
            # 数据无效或为0
            self.signal_jlink_log_add.emit("配置信息类型错误，请检查配置文件！\r\n")
            return

        # 根据选择的设备类型拼接动态库路径
        library_path = os.path.join(".", "img", "generateID.dll")
        # print(library_path)
        
         # 检查文件是否存在
        if not os.path.exists(library_path):
            QMessageBox.critical(self, "错误", "动态库文件不存在！")
            return

        # 加载动态链接库
        try:
            lib = cdll.LoadLibrary(library_path)
        except Exception as e:
            QMessageBox.critical(self, "错误", f"动态库加载失败：{e}")
            return

        input_str = device_config.get("imagetype")

        # 将字符串编码为字节，并创建一个可写的字节数组
        encoded_str = input_str.encode('utf-8')
        byte_array = bytearray(encoded_str)

        # 从可写的字节数组创建 ctypes 数组并获取其指针
        input_str_array = (c_ubyte * len(byte_array)).from_buffer(byte_array)
        input_str_ptr = cast(input_str_array, POINTER(c_ubyte))

        # 调用库中的函数
        result = lib.generateID(current_time.year, current_time.month, current_time.day, last_value + 1, input_str_ptr,inputproduct_info)

        if result == 0:
            try:
                shutil.move(r".\0xA000bin.bin", r".\img\0xA000bin.bin")
                self.signal_jlink_log_add.emit('生成的终端ID为：' + f"{current_time.year - 2000}" + f"{current_time.month:02d}" + f"{current_time.day:02d}" + f"{(last_value):04d}" +'，ID文件在img目录下，文件名：0xA000bin.bin' + '\r\n')

                # 更新INI文件中的日期和数值
                config.set("devInfo", "last_date", str(current_date))
                config.set("devInfo", "last_value", str(last_value + 1))
                with open(config_path, "w") as config_file:
                    config.write(config_file)
               
                # temp_dir = tempfile.gettempdir()
                # print("DLL缓存路径：", temp_dir)
                
                dir_path = os.path.dirname(os.path.abspath(sys.argv[0]))  # 获取当前主程序所在的目录路径
                config_file = os.path.join(dir_path, 'config.json')  # 拼接路径，获取配置文件的绝对路径
                
                # 调用合成脚本合成烧写hex文件
                # error_msgs = MergeHex.main(config_file)
                # 创建并启动线程
                merge_hex_thread = MergeHexThread(config_file)
                merge_hex_thread.start()
                # 等待线程执行完成
                merge_hex_thread.join()
                # 获取线程的返回值
                error_msgs = merge_hex_thread.error_msgs

                if error_msgs is None:
                    self.signal_jlink_log_add.emit('生成的hex烧写文件为：MergedHexFile.hex，保存在程序运行运行目录下，烧写地址为0x00000000' + '\r\n')
                else:
                    print('以下错误发生了：')
                    for error_msg in error_msgs:
                        self.signal_jlink_log_add.emit(error_msg)

            except Exception as e:
                self.signal_jlink_log_add.emit(f"移动文件时发生错误：{e}" + '\r\n')
                print(f"移动文件时发生错误：{e}")
        else:
            print("文件生成失败,错误码："+ str(result))
            self.signal_jlink_log_add.emit("文件生成失败,错误码："+ str(result))

    def __init__(self):
        try:
            super().__init__()
            self.jlink = None
            self.ui = Ui_MainWindow()#主窗体
            
            cfg = {}
            self.ui.setupUi(self)
            # self.uart_hd = uart_cfg_window(None, cfg)
            self.uart_cfg_hd = uart_cfg_window(self.single_uart_hd, cfg)
            self.cfg_dict = get_cfg_dict()
            uart_cfg = {}
            # print(self.cfg_dict)
            if 'uart_cfg' in self.cfg_dict.keys():
                if 'port' in self.cfg_dict['uart_cfg'].keys():
                    uart_cfg['port'] = self.cfg_dict['uart_cfg']['port']

                if 'bandrate' in self.cfg_dict['uart_cfg'].keys():
                    uart_cfg['bandrate'] = self.cfg_dict['uart_cfg']['bandrate']
                if 'data_bits' in self.cfg_dict['uart_cfg'].keys():
                    uart_cfg['data_bits'] = self.cfg_dict['uart_cfg']['data_bits']
                if 'sum' in self.cfg_dict['uart_cfg'].keys():
                    uart_cfg['sum'] = self.cfg_dict['uart_cfg']['sum']
                if 'stops' in self.cfg_dict['uart_cfg'].keys():
                    uart_cfg['stops'] = self.cfg_dict['uart_cfg']['stops']
                if 'rec_timeout' in self.cfg_dict['uart_cfg'].keys():
                    uart_cfg['rec_timeout'] = self.cfg_dict['uart_cfg']['rec_timeout']
                self.uart_cfg_hd.set_cfg(uart_cfg)
            
            self.single_uart_hd.connect(self.uart_rec_hd)
            check = [self.ui.checkBox,self.ui.checkBox_2, self.ui.checkBox_3]
            pathx = [self.ui.toolButton,self.ui.toolButton_2, self.ui.toolButton_3]
            address = [self.ui.lineEdit,self.ui.lineEdit_2, self.ui.lineEdit_3]

            for i in range(0, 3):
                ret = get_cfg_other('down_load_file%d'%(i + 1))
                if ret != None:
                    if 'enable' in ret.keys():
                        check[i].setChecked(bool(ret['enable']))

                    if 'path' in ret.keys():
                        pathx[i].setText(ret['path'])
                        self.file_path[i] = ret['path']
                    if 'address' in ret.keys():
                        address[i].setText(ret['address'])

            # self.ui.DevicelineEdit.setDisabled(True)

            for i in range(0, 100):
                ret = get_cfg_other('cfg%d' % i)

                if ret != None:
                    temp = get_cfg_other('cfg%d' % i)
                    self.cfg[temp['name']] = temp
                    self.cfg[temp['name']]['list'] = []
                    try:
                        files = os.listdir(self.cfg[temp['name']]['dir'])

                        for name in files:
                            if os.path.isdir('%s/%s' % (self.cfg[temp['name']]['dir'], name)):
                                self.cfg[temp['name']]['list'].append(name)   
                    except:
                        pass

            # print(self.cfg)
            try:
                self.names = list(self.cfg.keys())

                if len(self.names) > 0:
                    self.ui.comboBox_3.addItems(self.names)     
            except :
                pass  

            try:
                self.ui.comboBox_22.clear()
                temp = pylink.JLink()
                serial_list = []
                info = temp.connected_emulators()

                for item in info:
                    serial_list.append('{}'.format(item.SerialNumber))
                
                if len(serial_list):
                    self.ui.comboBox_22.addItems(serial_list)
            except:
                pass
        
            # 加载配置并设置设备参数
            config_loader = ConfigDeviceLoader()
            options = config_loader.loadDeviceConfig()
            if options is not None:
                self.ui.deviceTypeCb.addItems(options)
            else:
                print("No options loaded into the combo box.")

        except Exception as e:
            printf_except_info(e)

    def slot_jlink_bin_name_change_func(self, name):
        self.ui.comboBox_5.clear()
        try:
            if len(self.cfg[name]['list']) > 0:
                self.ui.comboBox_5.addItems(self.cfg[name]['list'])
            self.ui.DevicelineEdit.setText(self.cfg[name]['device'])
        except:
            pass

    def flash_file_cb(self, action, progress_string, percentage):
        # print(time.time(),action, progress_string, '%d'%percentage)
        self.set_speed(percentage)

    def slot_jlink_all_file(self):
        try:
            temp =  self.ui.comboBox_22.currentText()
            if temp == '':
                self.alarm('警告','请检查jlink是否正常接入 点击刷新')
                return

            if self.ui.DevicelineEdit.text() == '':
                self.alarm('警告','请选择设备号')
                return
            self.jlink = pylink.JLink()
            self.jlink.open(serial_no = self.ui.comboBox_22.currentText())
            # self.jlink.power_on()
            self.jlink.set_tif(pylink.enums.JLinkInterfaces.SWD)  # 成功返回True
            self.jlink.connect(self.ui.DevicelineEdit.text())  # 成功无返回
            self.jlink.set_reset_pin_low()
            time.sleep(0.05)
            self.jlink.set_reset_pin_high()
            self.jlink.reset()

            tempx =[self.ui.checkBox, self.ui.checkBox_2, self.ui.checkBox_3]
            address = [int(self.ui.lineEdit.text(), 16),int(self.ui.lineEdit_2.text(), 16),int(self.ui.lineEdit_3.text(), 16)]
            self.signal_jlink_log_clear.emit()

            for i in range(0, 3):
                if self.file_path[i] != '' and(tempx[i].isChecked()):
                    if '.hex' in self.file_path[i]:
                        ret = get_hex_info(self.file_path[i])
                        if ret[0] == ERR_NONE:
                            for key,val in ret[1].items():
                                hd = open('./temp.bin', 'wb')
                                hd.write(val)
                                hd.close()
                                dis = 'addresss:0x%x size:%d\n'%( key, len(val))
                                main_app_wdbg.info(dis)
                                self.signal_jlink_log_add.emit(get_time_str() + '  ' + dis)
                                self.jlink.flash_file('./temp.bin',key, on_progress= self.flash_file_cb)

                        pass
                    elif '.bin' in self.file_path[i]:
                        a = os.path.abspath(self.file_path[i])
                        hd = open(a, 'rb')
                        temp = hd.read(102400000)
                        hd.close()
                        hd = open('./temp.bin', 'wb')
                        hd.write(temp)
                        hd.close()
                        self.signal_jlink_log_add.emit(get_time_str() + '  ' + '文件名:%s  address:0x%x size:%d\n'%(self.file_path[i], address[i], len(temp)))
                        self.jlink.flash_file('./temp.bin', address[i], on_progress= self.flash_file_cb)
                    elif '.s19' in self.file_path[i]:
                        ret = get_s19_data(self.file_path[i])
                        if ret[0] == ERR_NONE:
                            for key,val  in ret[1].items():
                                hd = open('./temp.bin', 'wb')
                                hd.write(val)
                                hd.close()
                                dis = 'addresss:0x%x size:%d'%( key, len(val))
                                main_app_wdbg.info(dis)
                                self.signal_jlink_log_add.emit(get_time_str() + '  ' + dis + '\n')
                                self.jlink.flash_file('./temp.bin', key, on_progress= self.flash_file_cb)
            self.jlink.reset(1,False)
            self.signal_jlink_log_add.emit('下载成功')
        except Exception as e:
            msg = printf_except_info(e)
            self.signal_jlink_log_add.emit(msg)
    
    def slot_fareware_pub(self):
        pass

    def slot_select_file1(self):
        file_path, file_type = QFileDialog.getOpenFileName(self, '标题', os.getcwd(), '固件 (*.bin *.hex *.s19 *.py)')
        self.file_path[0] = file_path
        self.ui.toolButton.setText(file_path)
        set_cfg('down_load_file1', 'path',file_path)
    
    def slot_select_file2(self):
        file_path, file_type = QFileDialog.getOpenFileName(self, '标题', os.getcwd(), '固件 (*.bin *.hex *.s19 *.py)')
        self.file_path[1] = file_path
        self.ui.toolButton_2.setText(file_path)
        set_cfg('down_load_file2', 'path',file_path)

    def slot_select_file3(self):
        file_path, file_type = QFileDialog.getOpenFileName(self, '标题', os.getcwd(), '固件 (*.bin *.hex *.s19 *.py)')
        self.file_path[2] = file_path
        self.ui.toolButton_3.setText(file_path)
        set_cfg('down_load_file3', 'path',file_path)
    def slot_enable(self):
        set_cfg('down_load_file1', 'enable',self.ui.checkBox.isChecked())
        set_cfg('down_load_file2', 'enable',self.ui.checkBox_2.isChecked())
        set_cfg('down_load_file3', 'enable',self.ui.checkBox_3.isChecked())

    def slot_set_address(self):
        set_cfg('down_load_file1', 'address',self.ui.lineEdit.text())
        set_cfg('down_load_file2', 'address',self.ui.lineEdit_2.text())
        set_cfg('down_load_file3', 'address',self.ui.lineEdit_3.text())
        pass
    def slot_jlink_download(self):
        try:
            self.signal_jlink_log_clear.emit()
            filex = os.path.join(
                self.cfg[self.ui.comboBox_3.currentText()]['dir'] + '\\' + self.ui.comboBox_5.currentText(),
                self.cfg[self.ui.comboBox_3.currentText()]['file_name'])
            self.signal_jlink_log_add.emit(get_time_str() + '  ' + filex + '\n')

            temp =  self.ui.comboBox_22.currentText()
            if temp == '':
                self.alarm('警告','请检查jlink是否正常接入 点击刷新')
                return
            
            self.jlink = pylink.JLink()
            self.jlink.open(serial_no = self.ui.comboBox_22.currentText())
            # self.jlink.power_on()
            self.jlink.set_tif(pylink.enums.JLinkInterfaces.SWD)  # 成功返回True
            self.jlink.connect(self.ui.DevicelineEdit.text())  # 成功无返回
            self.jlink.set_reset_pin_low()
            time.sleep(0.05)
            self.jlink.set_reset_pin_high()
            self.jlink.reset()
            if self.ui.comboBox_23.currentIndex() != 1:
                self.jlink.erase()
            if '.hex' in filex:
                ret = get_hex_info(filex)
                if ret[0] == ERR_NONE:
                    for key,val in ret[1].items():
                        hd = open('./temp.bin', 'wb')
                        hd.write(val)
                        hd.close()
                        dis = 'addresss:0x%x size:%d\n'%( key, len(val))
                        main_app_wdbg.info(dis)
                        self.signal_jlink_log_add.emit(get_time_str() + '  ' + dis)
                        self.jlink.flash_file('./temp.bin',key, on_progress= self.flash_file_cb)

                pass
            elif '.bin' in filex:
                a = os.path.abspath(filex)
                hd = open(a, 'rb')
                temp = hd.read(102400000)
                hd.close()
                hd = open('./temp.bin', 'wb')
                hd.write(temp)
                hd.close()
                if 'base_addr' in self.cfg[self.ui.comboBox_3.currentText()].keys():
                    self.jlink.flash_file('./temp.bin', int(self.cfg[self.ui.comboBox_3.currentText()]['base_addr'], 16), on_progress= self.flash_file_cb)
            elif '.s19' in filex:
                ret = get_s19_data(filex)
                if ret[0] == ERR_NONE:
                    for key,val  in ret[1].items():
                        hd = open('./temp.bin', 'wb')
                        hd.write(val)
                        hd.close()
                        dis = 'addresss:0x%x size:%d'%( key, len(val))
                        main_app_wdbg.info(dis)
                        self.signal_jlink_log_add.emit(get_time_str() + '  ' + dis + '\n')
                        self.jlink.flash_file('./temp.bin', key, on_progress= self.flash_file_cb)
                pass
            self.jlink.reset()
            self.signal_jlink_log_add.emit('下载成功')
        except JLinkException as e:
            self.signal_jlink_log_add.emit('警告:{}'.format(e))

        except Exception as e:
            msg = '{}:{} {} '.format(e.__traceback__.tb_frame.f_globals["__file__"], e.__traceback__.tb_lineno, e)
            self.signal_jlink_log_add.emit(msg)
        finally:
            if self.jlink is not None:
                self.jlink.close()
            self.jlink = None
    
    def slot_jlink_read_mem(self):
        try:
            temp =  self.ui.comboBox_22.currentText()
            if temp == '':
                self.alarm('警告','请检查jlink是否正常接入 点击刷新')
                return
        
            self.signal_jlink_log_clear.emit()
            self.signal_jlink_log_add.emit('{}'.format(get_time_str()) + '\r\n')
            temp = self.ui.lineEdit_10.text().replace('0x','').replace('0X','')
            hex_val = int(temp, 16)
            self.jlink = pylink.JLink()
            self.jlink.open()
            self.jlink.set_tif(pylink.enums.JLinkInterfaces.SWD)  # 成功返回True
            self.jlink.connect(self.ui.DevicelineEdit.text())  # 成功无返回
            temp = bytearray(self.jlink.memory_read(hex_val, int(self.ui.spinBox_12.value())))
            cfg = {}
            cfg['type'] = self.ui.comboBox_14.currentText()
            cfg['scale'] = self.ui.comboBox_13.currentText()
            cfg['biglit'] = self.ui.comboBox_10.currentText()
            self.signal_jlink_log_add.emit(get_dis_data(cfg,temp, self.ui.spinBox_15.value()))
        except JLinkException as e:
            self.signal_jlink_log_add.emit('警告:{}'.format(e))

        except Exception as e:
            msg = '读取失败..  {}:{} {} '.format(e.__traceback__.tb_frame.f_globals["__file__"],
                                                 e.__traceback__.tb_lineno, e)
            self.signal_jlink_log_add.emit(msg)
        finally:
            if self.jlink is not None:
                self.jlink.close()
                self.jlink = None

    def slot_jlink_renew(self):
        self.ui.comboBox_22.clear()
        temp = pylink.JLink()
        serial_list = []
        info = temp.connected_emulators()

        for item in info:
            serial_list.append('{}'.format(item.SerialNumber))
        
        if len(serial_list):
            self.ui.comboBox_22.addItems(serial_list)

    def slot_jlink_erase_chip(self):
        try:
            temp =  self.ui.comboBox_22.currentText()
            if temp == '':
                self.alarm('警告','请检查jlink是否正常接入 点击刷新 点击刷新')
                return
        
            self.signal_jlink_log_clear.emit()
            self.signal_jlink_log_add.emit(get_time_str() + '  开始执行擦除...\n')
            self.jlink = pylink.JLink()
            self.jlink.open()
            self.jlink.set_tif(pylink.enums.JLinkInterfaces.SWD)  # 成功返回True
            self.jlink.connect(self.ui.DevicelineEdit.text())  # 成功无返回
            self.jlink.set_reset_pin_low()
            time.sleep(0.05)
            self.jlink.set_reset_pin_high()
            self.jlink.reset()
            self.jlink.erase()
            log = 'core id:0x%x device:%d connected:%d\n' % (
            self.jlink.core_id(), self.jlink.device_family(), self.jlink.target_connected())
            self.signal_jlink_log_add.emit(log)
            self.signal_jlink_log_add.emit('擦除成功... ')
        except JLinkException as e:
            self.signal_jlink_log_add.emit('警告:{}'.format(e))

        except Exception as e:
            self.jlink.close()
            self.signal_jlink_log_add.emit('擦除失败... \n')
            msg = '{}:{} {} '.format(e.__traceback__.tb_frame.f_globals["__file__"], e.__traceback__.tb_lineno, e)
            self.signal_jlink_log_add.emit(msg)
        finally:
            if self.jlink is not None:
                self.jlink.close()
                self.jlink = None
    
    def slot_jlink_reset(self):
        try:
            temp =  self.ui.comboBox_22.currentText()
            if temp == '':
                self.alarm('警告','请检查jlink是否正常接入 点击刷新')
                return
            
            self.signal_jlink_log_clear.emit()
            self.signal_jlink_log_add.emit('{}'.format(get_time_str()))
            self.jlink = pylink.JLink()
            self.jlink.open()
            self.jlink.set_reset_pin_low()
            time.sleep(0.05)
            self.jlink.set_reset_pin_high()
            self.signal_jlink_log_add.emit('复位成功')
        except JLinkException as e:
            self.signal_jlink_log_add.emit('警告:{}'.format(e))

        except Exception as e:
            msg = '复位失败..  {}:{} {} '.format(e.__traceback__.tb_frame.f_globals["__file__"],
                                                 e.__traceback__.tb_lineno, e)
            self.signal_jlink_log_add.emit(msg)
        finally:
            if self.jlink is not None:
                self.jlink.close()
                self.jlink = None


    def slot_tool_get_crc32(self):
        try:
            now = self.ui.lineEdit_15.text()
            srcdata = binascii.a2b_hex(now.replace(' ','').replace('\n',''))
            crc32 = get_crc_data(srcdata)
            self.ui.lineEdit_16.setText('0x%08x'%(crc32))
        except:
            pass
        pass

    def rec_dis_req_func(self, msgx):
        try:
            cmd = msgx[0]

            if cmd == 'add':
                self.ui.plainTextEdit.appendPlainText(msgx[1])
        except Exception as e:
            printf_except_info(e)

    #弹窗显示警告信息方法。
    def alarm(self, note, msg):
        QMessageBox.information(self, note, '{}'.format(msg))

    #应用关闭。
    def closeEvent(self, a0: QtGui.QCloseEvent):
        try:
            if self.can_hd is not None:
                self.can_hd.stop_server(0)
            super().closeEvent(a0)
        except Exception as e:
            printf_except_info(e)


    #报文监测与发送.日志显示添加方法
    def dis_data(self, data):
        self.signal_dis.emit(('add', data))

    #map信息查询.操作下拉框.内容改变.槽函数
    def slot_edit_change(self, data):
        pass    
    #map信息查询.操作下拉框.序号改变.槽函数

    #报文监测与发送.报文显示.清空显示数据
    def slotclear_dis(self):
        self.ui.plainTextEdit.clear()



    def slot_change(self):
        pass


def main_func():
    try:
        app = QApplication(sys.argv)
        MainWindow = mian_window()
        # style_sheet = QSSLoader.read_qss_file( './black.qss')
        # MainWindow.setStyleSheet(style_sheet)   
        MainWindow.show()
        app.exec()
        MainWindow.stop()
        sys.exit()
    except Exception as e:
        printf_except_info(e)
        sys.exit()


if __name__ == '__main__':
    main_func()
